package com.phychips.serial;

import com.phychips.JniClass;
import com.phychips.common.OnBytesAvailableListener;
import com.phychips.rcp.RcpConst;
import com.phychips.rcp.RcpException;
import com.phychips.rcp.RcpLib;

public class SerialTranceiver
{
    private byte RCP_PRAMBL_LEN = 1;
    private byte RCP_HEADER_LEN = 4;
    private byte RCP_ENDMRK_LEN = 1;
    private byte RCP_HEADEND_LEN = (byte) (RCP_PRAMBL_LEN + RCP_HEADER_LEN + RCP_ENDMRK_LEN);
    private byte RCP_CRC_LEN = 2;
    private byte RCP_HEADEND_CRC_LEN = (byte) (RCP_HEADEND_LEN + RCP_CRC_LEN);

    public static final int MAX_BUF = 512;
    private Thread inputThread;

    static public String comport = new String("/dev/ttyUSB0");
    static public boolean mRunflag = false;
    
    public void change_comport(String newcomport)
    {
	comport = new String(newcomport);
    }

    public boolean open() throws RcpException
    {
	if(JniClass.open(comport) < 0)
	{
	    mRunflag = false;
	    return false;
	}
	else
	{
	    inputThread = new Thread(inputProcessor);
	    inputThread.start();

	    mRunflag = true;
	    return true;
	}
    }

    public void close() throws RcpException
    {
	if (mRunflag == true)
	    JniClass.close();

	mRunflag = false;
    }

    public void send(byte[] data, int length) throws RcpException
    {
	int res = 0;

	for (int i = 0; res >= 0 && i < length; i++)
	    res = JniClass.write(RcpLib.covertUbytetoInt(data[i]));
    }

    private Runnable inputProcessor = new Runnable()
    {
	public void run()
	{
	    while (mRunflag)
	    {
		try
		{
		    int recvlen = 0;
		    boolean added = false;
		    int i = 0;
		    int res = 0;
		    int payload_len = 0;
		    byte rbuf[] = new byte[MAX_BUF];

//		    for (i = 0; res >= 0 && i < MAX_BUF; i++)
		    while(true)
		    {
			res = JniClass.read();
			
			System.out.println("JniClass.read() = " + Integer.toString(res, 16)); 

			if(added)
			{
			    if(recvlen < (RCP_PRAMBL_LEN + RCP_HEADER_LEN))
			    {
				rbuf[recvlen++] = (byte)(res & 0xFF);
			    }
			    else if(recvlen == (RCP_PRAMBL_LEN + RCP_HEADER_LEN))
			    {
				rbuf[recvlen++] = (byte)(res & 0xFF);

				payload_len = RcpLib.convertByteArrayToInt(rbuf, 3, 2);
			    }
			    else
			    {
				rbuf[recvlen++] = (byte)(res & 0xFF);

				if (recvlen >= (RCP_HEADEND_CRC_LEN + payload_len))
				{
				    if(rbuf[RCP_PRAMBL_LEN + RCP_HEADER_LEN + payload_len] != RcpConst.ENDMARK)
					recvlen = 0;

				    break;
				}
				
				if (recvlen > MAX_BUF)
				    break;
			    }
			}
			else
			{
			    if ((byte)(res & 0xFF) == RcpConst.PREAMBLE)
			    {
				rbuf[recvlen++] = RcpConst.PREAMBLE;
				added = true;
			    }
			}
		    }
		    
		    if(recvlen <= RCP_HEADEND_CRC_LEN)
			continue;
		    else
		    {
			byte[] ba = new byte[recvlen];

			for(i = 0; i < ba.length; i++)
			    ba[i] = rbuf[i];
			
			notifyBytesAvailable(ba);
		    }
		}
		catch (Exception e)
		{
		    e.printStackTrace();
		}
		finally
		{

		}
	    }
	}
    };

    private OnBytesAvailableListener bytesAvailableListener = null;

    private void notifyBytesAvailable(byte[] rxData)
    {
	if (bytesAvailableListener != null)
	{
	    bytesAvailableListener.onBytesAvailable(rxData);
	}
    }
    
    public void registerBytesAvailableListener(OnBytesAvailableListener listener)
    {
	bytesAvailableListener = listener;
    }
}
